/**
 * Copyright (C), 2021-2024, 四信物联网有限公司
 * FileName: BeiDouQueueTask
 * Author:   Chapin
 * Date:     2024/9/30 17:40
 * Description: 北斗消息队列发送任务
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.fourfaith.iot.beidou.task;

import cn.hutool.core.util.HexUtil;
import com.fourfaith.common.pojo.ResultDto;
import com.fourfaith.iot.beidou.decodec.BeiDouContants;
import com.fourfaith.iot.beidou.decodec.BeiDouEncoder;
import com.fourfaith.iot.beidou.manager.SerialPortManager;
import com.fourfaith.iot.beidou.manager.TcpManager;
import com.fourfaith.iot.beidou.message.outbound.CCicrMessage;
import com.fourfaith.iot.beidou.pojo.bean.FkxxBean;
import com.fourfaith.iot.beidou.session.SessionFactory;
import com.fourfaith.iot.device.cloud.access.dubbo.pojo.param.BeiDouParam;
import com.fourfaith.iot.device.cloud.access.dubbo.pojo.param.QueueRemoveParam;
import com.fourfaith.iot.device.cloud.access.dubbo.service.IBeidouDubboService;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

import javax.annotation.Resource;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 【北斗消息队列发送任务】
 * @author Chapin
 * @create 2024/9/30
 * @since 1.0.0
 */
@Slf4j
@Component
public class BeiDouQueueTask {

    @Value("${tasker.second}")
    private Integer taskerSecond;

    @Value("${serialPort.enable}")
    private int serialEnable;

    @Resource
    private SerialPortManager serialPortManager;
    @Resource
    private TcpManager tcpManager;

    @DubboReference(timeout = 10000)
    private IBeidouDubboService beidouDubboService;

    private static final AtomicLong ATOMIC_TS = new AtomicLong();

    private void updateAtomicTs(long delayTs) {
        ATOMIC_TS.set(System.currentTimeMillis() + (taskerSecond + delayTs + 5) * 1000L);
    }

    @Scheduled(cron = "*/5 * * * * ?")
    public void beiDouQueue() {
        long waitUntilTs = ATOMIC_TS.get();
        long now = System.currentTimeMillis();
        if (waitUntilTs > now) {
            log.info("发送等待中,发射频度未到");
            return;
        } else {
            updateAtomicTs(0);
        }
        ResultDto<BeiDouParam> resultDto = null;
        try {
            resultDto = beidouDubboService.queueGetFirst();
            log.info("查询北斗队列:{}", resultDto);
        } catch (Exception e) {
            log.error("北斗队列读取失败", e);
        }
        if (resultDto == null || !resultDto.isSuccess() || resultDto.getData() == null) {
            updateAtomicTs(0);
            return;
        }
        BeiDouParam beiDouParam = resultDto.getData();
        FkxxBean fkxxBean = null;
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        try {
            if (serialEnable == 1) {
                fkxxBean = serialPortManager.send(beiDouParam);
            } else {
                fkxxBean = tcpManager.send(beiDouParam);
            }
        } catch (Exception e) {
            log.error("北斗消息发送失败", e);
        }
        stopWatch.stop();
        double totalTimeSeconds = stopWatch.getTotalTimeSeconds();
        log.info("执行耗时：{}", totalTimeSeconds);
        if (fkxxBean == null) {
            log.error("程序未就绪");
            return;
        }
        updateAtomicTs(fkxxBean.getDelayTime());
        log.info("北斗队列数据发送情况：{}", fkxxBean);

        QueueRemoveParam queueRemoveParam = new QueueRemoveParam();
        queueRemoveParam.setId(beiDouParam.getId());
        // 发送失败，加入队列重试
        if (!fkxxBean.getSuccess()) {
            beidouDubboService.requeue(queueRemoveParam);
            return;
        }
        beidouDubboService.queueRemoveOne(queueRemoveParam);
    }

    @Scheduled(fixedDelay = 10 * 60 * 1000, initialDelay = 1000)
    public void beiDouIcjc() {
        CCicrMessage cCicrMessage = new CCicrMessage();
        cCicrMessage.setInstructionType("0");
        cCicrMessage.setSubordinateUser("00");
        byte[] sendBytes = new byte[1024];
        try {
            sendBytes = BeiDouEncoder.encodeToByte(cCicrMessage);
        } catch (Exception e){
            log.error("编码失败", e);
        }
        if(serialEnable == 1){
            serialPortManager.getSerialPort().writeBytes(sendBytes,sendBytes.length);
            log.info("串口发送IC检查:{}", HexUtil.encodeHexStr(sendBytes));
        }else {
            Channel channel = SessionFactory.getSession().getChannel(BeiDouContants.BEI_DOU3);
            if(channel != null){
                log.info("TCP发送IC检查{}", HexUtil.encodeHexStr(sendBytes));
                channel.writeAndFlush(Unpooled.copiedBuffer(sendBytes));
            }else {
                log.error("tcp,IC检查,服务未打开");
            }
        }
    }


}